#!/usr/bin/env python
# -*- coding: utf-8 -*-

"""
    类ClientSmtp，封装了smtplib模块
用于前端client的调用，实现对smtp服务器
的连接，与邮件发送等操作。目前可能还有未知
bug的存在。
    注意点：该类中 username,password,ssl均没有写get/set方法，
username,password属性的赋值在login()方法中,ssl属性赋值在
get_smtp()中，特此注明，方便后续随GUI前端要求做相应改动。
"""

import smtplib


class ClientSmtp:
    def __init__(self, host=None, port=None, local_hostname=None):
        self.__host = host  # smtp服务器主机地址
        self.__port = port  # smtp服务器服务端口号
        self.__local_hostname = local_hostname  # 本地主机名
        self.__smtp = None  # smtp连接
        self.__username = None
        self.__password = None
        self.__ssl = None

    def set_host(self, host):
        self.__host = host

    def set_port(self, port):
        self.__port = port

    def set_username(self, username):
        self.__username = username

    def set_password(self, password):
        self.__password = password

    def set_local_hostname(self, local_hostname):
        self.__local_hostname = local_hostname

    def get_username(self):
        return self.__username

    def get_password(self):
        return self.__password

    def get_host(self):
        return self.__host

    def get_port(self):
        return self.__port

    def get_local_hostname(self):
        return self.__local_hostname

    # host、port、local_hostname属性的set/get方法

    def get_smtp(self, ssl=False):
        """
        向实例化的ClientSMTP中smtp属性赋予相对应smtp对象;
        :param ssl: is/not ssl connection;
        :return: None
        """
        self.__ssl = ssl
        if not ssl:
            self.__smtp = smtplib.SMTP()
        elif ssl:
            self.__smtp = smtplib.SMTP_SSL()

    def get_connect(self):
        """
        使smtp属性对象获得连接;
        :return: (True/False,success msg/error msg)
        """
        try:
            status = self.__smtp.connect(self.__host, self.__port)
            if status[0] == 220:
                return True, status[1]
            else:
                return False, status[1]
        except Exception as err:
            return False, str(err)

    def is_connecting(self):
        """
        检查smtp属性对象是否处于连接正常中;
        :return: True/False
        """
        try:
            status = self.__smtp.helo()
            if status[0] == 250:
                return True
            else:
                return False
        except smtplib.SMTPServerDisconnected:
            return False

    def reconnect(self):
        """
        断线重连功能;
        :return: (True/False,"success"/err message)
        """
        try:
            if self.is_connecting():
                return True, "connected!"
            else:
                status = self.get_connect()
                if status:
                    return True, "Reconnect success!"
                else:
                    return False, status[1]
        except Exception as err:
            return False, str(err)

    def login(self, username, password):
        """
        登陆smtp服务器;
        :param username: (String);
        :param password: (String);
        :return: (True/False,success msg/error msg)
        """
        self.__username = username
        self.__password = password
        if not self.is_connecting():
            self.get_connect()
        self.__smtp.ehlo()
        try:
            status = self.__smtp.login(username, password)
        except smtplib.SMTPAuthenticationError:
            self.__smtp.starttls()
            status = self.__smtp.login(username, password)
        if status[0] == 235:
            return True, status[1]
        else:
            return False, status[1]

    def send_mail(self, from_address, to_address, msg):
        try:
            self.__smtp.sendmail(from_address, to_address, msg)
            return True, "发送成功"
        except Exception as err:
            if "530" in str(err):
                self.__smtp.starttls()
                self.__smtp.sendmail(from_address, to_address, msg)
                return True, "发送成功"
            return False, str(err)

    def quit(self):
        """
        退出服务器
        :return: True/False 操作成功/失败
        """
        status = self.__smtp.quit()
        if status[0] == 221:
            return True
        else:
            return False


if __name__ == '__main__':
    pass